home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / What's New? / Development Kits / Display Manager SDK v1.1 / Display Manager Sample Code / Play Video Sample / verbose debug code / RequestVideo.c < prev   
Encoding:
C/C++ Source or Header  |  1996-03-05  |  28.9 KB  |  776 lines  |  [TEXT/MMCC]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    MacOS™ Sample Code
  4. #    
  5. #    Written by: Eric Anderson
  6. #     AppleLink: ERIC3
  7. #     AOL: ERICTHREE
  8. #
  9. #    Display Manager sample code
  10. #
  11. #    RequestVideo
  12. #
  13. #    RequestVideo.c    -    C Code
  14. #
  15. #    Copyright © 1995 Apple Computer, Inc.
  16. #    All rights reserved.
  17. #
  18. #    5/31/95        ewa        Added RVGetCurrentVideoSetting and RVConfirmVideoRequest routines
  19. #                        to make it easy to revert back to where you came from and to give
  20. #                        the user a chance to confirm the new setting if the new mode was
  21. #                        valid (ie: the card supports it) but not safe (the monitor may not).
  22. #    5/24/95        ewa        Give the kAllValidModesBit requestFlags option for safe only or all
  23. #                        valid resolution timings.
  24. #
  25. #
  26. #
  27. #    Components:    PlayVideo.c            
  28. #                RequestVideo.c        
  29. #                RequestVideo.h        
  30. #                RequestVideo.rsrc        
  31. #
  32. #    RequestVideo demonstrates the usage of the Display Manager introduced
  33. #    with the PowerMacs and integrated into the system under System 7.5. With
  34. #    the RequestVideo sample code library, developers will be able to explore
  35. #    the Display Manager API by changing bit depth and screen resolution on
  36. #    multisync displays on built-in, NuBus, and PCI based video. Display Manager 1.0
  37. #    is built into the Systems included with the first PowerMacs up through System 7.5.
  38. #    Display Manager 2.0 is included with the release of the new PCI based PowerMacs,
  39. #    and will be included in post 7.5 System Software releases. 
  40. #    
  41. #    It is a good idea to reset the screen(s) to the original setting before exit
  42. #    since the call to RVSetVideoAsScreenPrefs() may not do the right thing under
  43. #    Display Manager 1.0 with certain video drivers.
  44. #
  45. #    For information on the use of this sample code, please the documentation in the Read Me file
  46. ------------------------------------------------------------------------------*/
  47.  
  48. #include "RequestVideo.h"
  49.  
  50. // Internal includes
  51. #include <Dialogs.h>
  52. #include <ROMDefs.h>
  53. #include <Devices.h>
  54. #include <Errors.h>
  55. #include <GestaltEqu.h>
  56. #include <Memory.h>
  57. #include <Palettes.h>
  58. #include <Slots.h>
  59. #include <StdIO.h>
  60. #include <Displays.h>
  61.  
  62. #include <stdlib.h>
  63.  
  64. //--------------------------------------------------------------
  65. //
  66. // Internal defines, structs, typedefs, and routine declarations
  67. //
  68. //--------------------------------------------------------------
  69. #define        KMonoDev            0                        // false (handy definitions for gdDevType settings)
  70. #define        kColorDev            1                        // true
  71. #define        char_Enter            0x03                    // for our filter proc
  72. #define        char_Return            0x0D                    //
  73. #define        iRevertItem            1                        // User buttons
  74. #define        iConfirmItem        2                        //
  75. #define        kSecondsToConfirm    8                        // seconds before confirm dialog is taken down
  76. #define        rConfirmSwtchAlrt    2735                    // ID of alert dialog
  77.  
  78. struct DepthInfo {
  79.     VDSwitchInfoRec            depthSwitchInfo;            // This is the switch mode to choose this timing/depth
  80.     VPBlock                    depthVPBlock;                // VPBlock (including size, depth and format)
  81. };
  82. typedef struct DepthInfo DepthInfo;
  83.  
  84. struct ListIteratorDataRec {
  85.     VDTimingInfoRec            displayModeTimingInfo;        // Contains timing flags and such
  86.     unsigned long            depthBlockCount;            // How many depths available for a particular timing
  87.     DepthInfo                *depthBlocks;                // Array of DepthInfo
  88. };
  89. typedef struct ListIteratorDataRec ListIteratorDataRec;
  90.  
  91. void GetRequestTheDM1Way (        VideoRequestRecPtr requestRecPtr,
  92.                                 GDHandle walkDevice);
  93.  
  94. void GetRequestTheDM2Way (        VideoRequestRecPtr requestRecPtr,
  95.                                 GDHandle walkDevice,
  96.                                 DMDisplayModeListIteratorUPP myModeIteratorProc,
  97.                                 DMListIndexType theDisplayModeCount,
  98.                                 DMListType *theDisplayModeList);
  99.  
  100. pascal void ModeListIterator (    void *userData,
  101.                                 DMListIndexType itemIndex,
  102.                                 DMDisplayModeListEntryPtr displaymodeInfo);
  103.  
  104. Boolean FindBestMatch (            VideoRequestRecPtr requestRecPtr,
  105.                                 short bitDepth,
  106.                                 unsigned long horizontal,
  107.                                 unsigned long vertical);
  108.  
  109. void GravitateMonitors (void);
  110.  
  111. pascal Boolean ConfirmAlertFilter (DialogPtr dlg, EventRecord *evt, short *itemHit);
  112.  
  113. //--------------------------------------------------------------
  114. //
  115. // Implementation of sample code
  116. //
  117. //--------------------------------------------------------------
  118. OSErr RVSetVideoRequest (VideoRequestRecPtr requestRecPtr)
  119. {
  120.     GDHandle        aMonitor;
  121.     Boolean            displayMgrPresent;
  122.     unsigned long    displayMgrVersion;
  123.     OSErr            err;
  124.     Boolean            isColor;
  125.     long            value = 0;
  126.  
  127.     Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
  128.     Gestalt(gestaltDisplayMgrAttr,&value);
  129.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  130.     if (displayMgrPresent)
  131.     {
  132.         if (requestRecPtr->displayMode && requestRecPtr->depthMode)
  133.         {
  134.             if (requestRecPtr->availBitDepth == 1)    // Based on avail bit depth, 
  135.                 isColor = KMonoDev;                    // set the device to a mono device, or
  136.             else isColor = kColorDev;                // set the device to a color device
  137.             SetDeviceAttribute(requestRecPtr->screenDevice,gdDevType,isColor);        
  138.             
  139.             // see how many monitors we have, aMonitor will be nil if we have only one.
  140.             aMonitor = DMGetFirstScreenDevice (dmOnlyActiveDisplays);            // get the first guy
  141.             aMonitor = DMGetNextScreenDevice ( aMonitor, dmOnlyActiveDisplays );    // get the next guy
  142.             
  143.             if (nil == aMonitor || displayMgrVersion >= 0x00020000)
  144.             {
  145.                 printf ("DMSetDisplayMode: second monitor & DM version: %d, %d\n", aMonitor, displayMgrVersion);
  146.                 // only call DMSetDisplayMode if we have one monitor or DM2.0 is installed
  147.                 // since DM1.0 does not automatically gravitate monitors and our gravitate code
  148.                 // is not implemented.
  149.                 err = DMSetDisplayMode(    requestRecPtr->screenDevice,    // GDevice
  150.                         requestRecPtr->displayMode,                        // DM1.0 uses this
  151.                         &requestRecPtr->depthMode,                        // DM1.0 uses this
  152.                         (unsigned long) &(requestRecPtr->switchInfo),    // DM2.0 uses this rather than displayMode/depthMode combo
  153.                         nil);
  154.                 if (noErr == err)
  155.                 {
  156.                     // Do the monitor gravitate here if we are using a version less than DM2.0
  157.                     if (displayMgrVersion < 0x00020000)
  158.                         GravitateMonitors ();
  159.                 }
  160.                 else if (kDMDriverNotDisplayMgrAwareErr == err)
  161.                 {
  162.                     // DM not supported by driver, so all we can do is set the bit depth
  163.                     printf ("setting depth only\n");
  164.                     err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
  165.                 }
  166.             }
  167.             else
  168.             {
  169.                 // we have more than one monitor and DM1.0 is installed, so all we can do is set the bit depth
  170.                 printf ("setting depth only\n");
  171.                 err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
  172.             }
  173.             
  174.             return (err);    // we could try to set the request
  175.         }
  176.     }
  177.     return (-1);    // return a generic error
  178. }
  179.  
  180. // This extern should be removed once this function is formally defined in Displays.h
  181. extern pascal OSErr DMUseScreenPrefs(Boolean usePrefs, Handle displayState)
  182.  THREEWORDINLINE(0x303C, 0x03EC, 0xABEB);
  183.  
  184. OSErr RVSetVideoAsScreenPrefs (void)
  185. {
  186.     Handle        displaystate;
  187.     Boolean        displayMgrPresent;
  188.     OSErr        err;                    
  189.     long        value = 0;
  190.  
  191.     Gestalt(gestaltDisplayMgrAttr,&value);
  192.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  193.     if (displayMgrPresent)
  194.     {
  195.         if (noErr != (err = DMBeginConfigureDisplays (&displaystate)))    // Tell the world it is about to change
  196.             printf ("DMBeginConfigureDisplays error: %d\n", err);
  197.         if (noErr != (err = DMUseScreenPrefs (true, displaystate)))        // Make the change
  198.             printf ("DMBeginConfigureDisplays error: %d\n", err);
  199.         if (noErr != (err = DMEndConfigureDisplays (displaystate)))        // Tell the world the change is over
  200.             printf ("DMBeginConfigureDisplays error: %d\n", err);
  201.         
  202.         return (noErr);    // we (maybe) set the world back to a known setting
  203.     }
  204.     return (-1);    // return a generic error
  205. }
  206.  
  207. OSErr RVGetCurrentVideoSetting (VideoRequestRecPtr requestRecPtr)
  208. {
  209.     unsigned long        displayMgrVersion;
  210.     OSErr                error = paramErr;
  211.     CntrlParam            pBlock;
  212.     VDSwitchInfoRec        switchInfo;
  213.     AuxDCEHandle        theDCE;
  214.     VDSwitchInfoRec        videoMode;        
  215.  
  216.     requestRecPtr->availBitDepth            = 0;    // init to default - you can do it if it is important to you
  217.     requestRecPtr->availHorizontal            = 0;
  218.     requestRecPtr->availVertical            = 0;
  219.     requestRecPtr->availFlags                = 0;
  220.     requestRecPtr->displayMode                = -1; 
  221.     requestRecPtr->depthMode                = -1;
  222.     requestRecPtr->switchInfo.csMode        = 0;
  223.     requestRecPtr->switchInfo.csData        = 0;
  224.     requestRecPtr->switchInfo.csPage        = 0;
  225.     requestRecPtr->switchInfo.csBaseAddr    = 0;
  226.     requestRecPtr->switchInfo.csReserved    = 0;
  227.     
  228.     Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
  229.     if (requestRecPtr->screenDevice)
  230.     {
  231.         if (displayMgrVersion >= 0x00020000)
  232.         {    // get the info the DM 2.0 way
  233.             error = DMGetDisplayMode(requestRecPtr->screenDevice, &switchInfo);
  234.             if (noErr == error)
  235.             {
  236.                 requestRecPtr->depthMode            = switchInfo.csMode;
  237.                 requestRecPtr->displayMode            = switchInfo.csData; 
  238.                 requestRecPtr->switchInfo.csMode    = switchInfo.csMode;
  239.                 requestRecPtr->switchInfo.csData    = switchInfo.csData;
  240.             }
  241.             printf ("RVGetCurrentVideoSetting DM2 displayMode: %d\n", requestRecPtr->displayMode);
  242.             printf ("RVGetCurrentVideoSetting DM2 depthMode: %d\n", requestRecPtr->depthMode);
  243.             return (error);    // we (maybe) set the world back to a known setting
  244.         }
  245.         else
  246.         {    // get the info the DM 1.0 way
  247.             videoMode.csMode = -1;        // init to bogus value
  248.             videoMode.csData = -1;        // init to bogus value            
  249.             pBlock.ioNamePtr = nil;
  250.             pBlock.ioCRefNum = (*(requestRecPtr->screenDevice))->gdRefNum;
  251.             pBlock.csCode = cscGetCurMode;
  252.             *(Ptr *)&pBlock.csParam[0] = (Ptr)&videoMode;
  253.                 
  254.             error = PBStatusSync((ParmBlkPtr )&pBlock);    // ask the driver first....since we trust it the most
  255.                 
  256.             if ( noErr == error && ((-1 == videoMode.csMode) || (-1 == videoMode.csData)) )
  257.                 error = statusErr;
  258.             
  259.             if (noErr != error)    // if the driver has no clue fill it videoMode by hand as a last resort
  260.             {    
  261.                 theDCE = (AuxDCEHandle)GetDCtlEntry((*(requestRecPtr->screenDevice))->gdRefNum);
  262.                 
  263.                 if( theDCE )
  264.                 {
  265.                     videoMode.csData = (unsigned char)(*theDCE)->dCtlSlotId; 
  266.                     videoMode.csMode = (*(requestRecPtr->screenDevice))->gdMode;
  267.                     error = noErr;
  268.                 }
  269.             }
  270.             if (noErr == error)    // Set our data
  271.             {
  272.                 requestRecPtr->displayMode            = videoMode.csData; 
  273.                 requestRecPtr->depthMode            = videoMode.csMode;
  274.                 requestRecPtr->switchInfo.csMode    = videoMode.csMode;
  275.                 requestRecPtr->switchInfo.csData    = videoMode.csData;
  276.             }
  277.             printf ("RVGetCurrentVideoSetting DM1 displayMode: %d\n", requestRecPtr->displayMode);
  278.             printf ("RVGetCurrentVideoSetting DM1 depthMode: %d\n", requestRecPtr->depthMode);
  279.             return (error);    // we (maybe) set the world back to a known setting
  280.         }
  281.     }
  282.     return (-1);
  283. }
  284.  
  285. pascal Boolean ConfirmAlertFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
  286. {
  287.     char charCode;
  288.     Boolean enterORreturn;
  289.     Boolean returnValue = false;
  290.  
  291.     if (0 == GetWRefCon(theDialog))
  292.         SetWRefCon (theDialog,TickCount());
  293.     else
  294.     {
  295.         if (GetWRefCon(theDialog) + kSecondsToConfirm * 60 < TickCount())
  296.         {
  297.             returnValue = true;
  298.             theEvent->what = nullEvent;
  299.             *itemHit = 1;
  300.         }
  301.         else
  302.         {
  303.             if (theEvent->what == keyDown)
  304.             {
  305.                 charCode = (char)theEvent->message & charCodeMask;
  306.                 enterORreturn = (charCode == (char)char_Return) || (charCode == (char)char_Enter);
  307.                 if (enterORreturn)
  308.                 {
  309.                     theEvent->what = nullEvent;
  310.                     returnValue = true;
  311.                     *itemHit = iRevertItem;
  312.                     if (enterORreturn && (0 != (theEvent->modifiers & optionKey)))
  313.                         *itemHit = iConfirmItem;
  314.                 }
  315.             }
  316.         }
  317.     }
  318.     return (returnValue);
  319. }
  320.  
  321. OSErr RVConfirmVideoRequest (VideoRequestRecPtr requestRecPtr)
  322. {
  323.     short            alertReturn;        // Alert() return value
  324.     ModalFilterUPP    confirmFilterUPP;    // got to have us one of them new fangled UPP thingies
  325.     
  326.     if (requestRecPtr->availFlags & 1<<kModeValidNotSafeBit)
  327.     {    // new mode is valid but not safe, so ask user to confirm
  328.         SetCursor(&qd.arrow);                                        // have to show the arrow
  329.  
  330.         confirmFilterUPP = NewModalFilterProc (ConfirmAlertFilter);    // create a new modal filter proc UPP
  331.         alertReturn = Alert(rConfirmSwtchAlrt, confirmFilterUPP);    // alert the user
  332.         DisposeRoutineDescriptor (confirmFilterUPP);                // of course there is no DisposeModalFilterProc...
  333.         
  334.         if (alertReturn != iConfirmItem)
  335.             return (-1);                            // tell the caller to switch back to a known setting
  336.         else return (noErr);                        // all is well with the new setting, just leave it
  337.     }
  338.     return (noErr);                                    // the mode was safe, so do nothing
  339. }
  340.  
  341.  
  342. OSErr RVRequestVideoSetting (VideoRequestRecPtr requestRecPtr)
  343. {
  344.     Boolean                            displayMgrPresent;
  345.     short                            iCount = 0;                    // just a counter of GDevices we have seen
  346.     DMDisplayModeListIteratorUPP    myModeIteratorProc = nil;    // for DM2.0 searches
  347.     SpBlock                            spBlock;
  348.     Boolean                            suppliedGDevice;    
  349.     DisplayIDType                    theDisplayID;                // for DM2.0 searches
  350.     DMListIndexType                    theDisplayModeCount;        // for DM2.0 searches
  351.     DMListType                        theDisplayModeList;            // for DM2.0 searches
  352.     long                            value = 0;
  353.     GDHandle                        walkDevice = nil;            // for everybody
  354.  
  355.     Gestalt(gestaltDisplayMgrAttr,&value);
  356.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  357.     displayMgrPresent=displayMgrPresent && (SVersion(&spBlock)==noErr);    // need slot manager
  358.     if (displayMgrPresent)
  359.     {
  360.         printf("\n");
  361.         printf("_______________________________________\n");
  362.         printf("Walk all the GDevices looking for video\n");
  363.     
  364.         // init the needed data before we start
  365.         if (requestRecPtr->screenDevice)                            // user wants a specifc device?
  366.         {
  367.             walkDevice = requestRecPtr->screenDevice;
  368.             suppliedGDevice = true;
  369.         }
  370.         else
  371.         {
  372.             walkDevice = DMGetFirstScreenDevice (dmOnlyActiveDisplays);            // for everybody
  373.             suppliedGDevice = false;
  374.         }
  375.         
  376.         myModeIteratorProc = NewDMDisplayModeListIteratorProc(ModeListIterator);    // for DM2.0 searches
  377.     
  378.         // Note that we are hosed if somebody changes the gdevice list behind our backs while we are iterating....
  379.         // ...now do the loop if we can start
  380.         if( walkDevice && myModeIteratorProc) do // start the search
  381.         {
  382.             iCount++;        // GDevice we are looking at (just a counter)
  383.             printf("\n");
  384.             printf("GDevice #%d at location %d.\n",iCount, walkDevice);
  385.             if( noErr == DMGetDisplayIDByGDevice( walkDevice, &theDisplayID, false ) )    // DM1.0 does not need this, but it fits in the loop
  386.             {
  387.                 theDisplayModeCount = 0;    // for DM2.0 searches
  388.                 if (noErr == DMNewDisplayModeList(theDisplayID, 0, 0, &theDisplayModeCount, &theDisplayModeList) )
  389.                 {
  390.                     // search NuBus & PCI the new kool way through Display Manager 2.0
  391.                     printf("Find request the DM2.0 way\n");
  392.                     GetRequestTheDM2Way (requestRecPtr, walkDevice, myModeIteratorProc, theDisplayModeCount, &theDisplayModeList);
  393.                     DMDisposeList(theDisplayModeList);    // now toss the lists for this gdevice and go on to the next one
  394.                 }
  395.                 else
  396.                 {
  397.                     // search NuBus only the old disgusting way through the slot manager
  398.                     printf("Find request the DM1.0 way\n");
  399.                     GetRequestTheDM1Way (requestRecPtr, walkDevice);
  400.                 }
  401.             }
  402.         } while ( !suppliedGDevice && nil != (walkDevice = DMGetNextScreenDevice ( walkDevice, dmOnlyActiveDisplays )) );    // go until no more gdevices
  403.         if( myModeIteratorProc )
  404.             DisposeRoutineDescriptor(myModeIteratorProc);
  405.         return (noErr);    // we were able to get the look for a match
  406.     }
  407.     return (-1);        // return a generic error
  408. }
  409.  
  410. void GetRequestTheDM1Way (VideoRequestRecPtr requestRecPtr, GDHandle walkDevice)
  411. {
  412.     AuxDCEHandle myAuxDCEHandle;
  413.     unsigned long    depthMode;
  414.     unsigned long    displayMode;
  415.     OSErr            error;
  416.     OSErr            errorEndOfTimings;
  417.     short            height;
  418.     short            jCount = 0;
  419.     Boolean            modeOk;
  420.     SpBlock            spAuxBlock;
  421.     SpBlock            spBlock;
  422.     unsigned long    switchFlags;
  423.     VPBlock            *vpData;
  424.     short            width;
  425.  
  426.     myAuxDCEHandle = (AuxDCEHandle) GetDCtlEntry((**walkDevice).gdRefNum);    
  427.     spBlock.spSlot = (**myAuxDCEHandle).dCtlSlot;
  428.     spBlock.spID = (**myAuxDCEHandle).dCtlSlotId;
  429.     spBlock.spExtDev = (**myAuxDCEHandle).dCtlExtDev;
  430.     spBlock.spHwDev = 0;                                // we are going to get this pup
  431.     spBlock.spParamData = 1<<foneslot;                    // this slot, enabled, and it better be here.
  432.     spBlock.spTBMask = 3;                                // don't have constants for this yet
  433.     errorEndOfTimings = SGetSRsrc(&spBlock);            // get the spDrvrHW so we know the ID of this puppy. This is important
  434.                                                         // since some video cards support more than one display, and the spDrvrHW
  435.                                                         // ID can, and will, be used to differentiate them.
  436.     
  437.     if ( noErr == errorEndOfTimings )
  438.     {
  439.         // reinit the param block for the SGetTypeSRsrc loop, keep the spDrvrHW we just got
  440.         spBlock.spID = 0;                                // start at zero, 
  441.         spBlock.spTBMask = 2;                            // 0b0010 - ignore DrvrSW - why ignore the SW side? Is it not important for video?
  442.         spBlock.spParamData = (1<<fall) + (1<<foneslot) + (1<<fnext);    // 0b0111 - this slot, enabled or disabled, so we even get 640x399 on Blackbird
  443.         spBlock.spCategory=catDisplay;
  444.         spBlock.spCType=typeVideo;
  445.         errorEndOfTimings = SGetTypeSRsrc(&spBlock);    // but only on 7.0 systems, not a problem since we require DM1.0
  446.         
  447.         // now, loop through all the timings for this GDevice
  448.         if ( noErr == errorEndOfTimings ) do
  449.         {
  450.             // now, loop through all possible depth modes for this timing mode
  451.             displayMode = (unsigned char)spBlock.spID;    // "timing mode, ie:resource ref number"
  452.             for (jCount = firstVidMode; jCount<= sixthVidMode; jCount++)
  453.             {
  454.                 depthMode = jCount;        // vid mode
  455.                 error = DMCheckDisplayMode(walkDevice,displayMode,depthMode,&switchFlags,0,&modeOk);
  456.     
  457.                 // only if the mode is safe or we override it with the kAllValidModesBit request flag
  458.                 if (    noErr == error &&
  459.                         modeOk &&
  460.                         (    switchFlags & 1<<kNoSwitchConfirmBit ||
  461.                             requestRecPtr->requestFlags & 1<<kAllValidModesBit
  462.                         )
  463.                     )
  464.                 {
  465.                     // have a good displayMode/depthMode combo - now lets look inside
  466.                     spAuxBlock = spBlock;                // don't ruin the iteration spBlock!!
  467.                     spAuxBlock.spID = depthMode;        // vid mode
  468.                     error=SFindStruct(&spAuxBlock);        // get back a new spsPointer
  469.                     if (noErr == error)                    // keep going if no error…
  470.                     {
  471.                         spAuxBlock.spID = 0x01;            // mVidParams request
  472.                         error=SGetBlock (&spAuxBlock);    // use the new spPointer and get back...a NewPtr'ed spResult
  473.                         if (noErr == error)                // …keep going if no error…
  474.                         {                                // We have data! lets have a look
  475.                             vpData = (VPBlock*)spAuxBlock.spResult;
  476.                             height = vpData->vpBounds.bottom;    // left and top are usually zero
  477.                             width = vpData->vpBounds.right;
  478.                             
  479.                             // print screen resolution - all the data
  480.                             printf("Mode: %d, Depth: %d, Resolution: %dH x %dV\n",
  481.                                 jCount,
  482.                                 vpData->vpPixelSize,
  483.                                 vpData->vpBounds.right,
  484.                                 vpData->vpBounds.bottom);
  485.                             printf("Components per Pixel: %d, bits per Component: %d\n",
  486.                                 vpData->vpCmpCount,
  487.                                 vpData->vpCmpSize);
  488.  
  489.                             if (FindBestMatch (requestRecPtr, vpData->vpPixelSize, vpData->vpBounds.right, vpData->vpBounds.bottom))
  490.                             {
  491.                                 requestRecPtr->screenDevice = walkDevice;
  492.                                 requestRecPtr->availBitDepth = vpData->vpPixelSize;
  493.                                 requestRecPtr->availHorizontal = vpData->vpBounds.right;
  494.                                 requestRecPtr->availVertical = vpData->vpBounds.bottom;
  495.                                 requestRecPtr->displayMode = displayMode;
  496.                                 requestRecPtr->depthMode = depthMode;
  497.                                 requestRecPtr->switchInfo.csMode = depthMode;                // fill in for completeness
  498.                                 requestRecPtr->switchInfo.csData = displayMode;
  499.                                 requestRecPtr->switchInfo.csPage = 0;
  500.                                 requestRecPtr->switchInfo.csBaseAddr = 0;
  501.                                 requestRecPtr->switchInfo.csReserved = 0;
  502.                                 if (switchFlags & 1<<kNoSwitchConfirmBit)
  503.                                     requestRecPtr->availFlags = 0;                            // mode safe
  504.                                 else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;    // mode valid but not safe, requires user validation of mode switch
  505.                             }
  506.  
  507.                             if (spAuxBlock.spResult) DisposePtr ((Ptr)spAuxBlock.spResult);    // toss this puppy when done
  508.                         }
  509.                     }
  510.                 }
  511.             }
  512.             // go around again, looking for timing modes for this GDevice
  513.             spBlock.spTBMask = 2;        // ignore DrvrSW
  514.             spBlock.spParamData =  (1<<fall) + (1<<foneslot) + (1<<fnext);    // next resource, this slot, whether enabled or disabled
  515.             errorEndOfTimings = SGetTypeSRsrc(&spBlock);    // and get the next timing mode
  516.         } while ( noErr == errorEndOfTimings );    // until the end of this GDevice
  517.     }
  518.  
  519. }
  520.  
  521. pascal void ModeListIterator(void *userData, DMListIndexType, DMDisplayModeListEntryPtr displaymodeInfo)
  522. {
  523.     unsigned long            depthCount;
  524.     short                    iCount;
  525.     ListIteratorDataRec        *myIterateData        = (ListIteratorDataRec*) userData;
  526.     DepthInfo                *myDepthInfo;
  527.     
  528.     // set user data in a round about way
  529.     myIterateData->displayModeTimingInfo        = *displaymodeInfo->displayModeTimingInfo;
  530.     
  531.     // now get the DMDepthInfo info into memory we own
  532.     depthCount = displaymodeInfo->displayModeDepthBlockInfo->depthBlockCount;
  533.     myDepthInfo = (DepthInfo*)NewPtrClear(depthCount * sizeof(DepthInfo));
  534.  
  535.     // set the info for the caller
  536.     myIterateData->depthBlockCount = depthCount;
  537.     myIterateData->depthBlocks = myDepthInfo;
  538.  
  539.     // and fill out all the entries
  540.     if (depthCount) for (iCount=0; iCount < depthCount; iCount++)
  541.     {
  542.         myDepthInfo[iCount].depthSwitchInfo = 
  543.             *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthSwitchInfo;
  544.         myDepthInfo[iCount].depthVPBlock = 
  545.             *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthVPBlock;
  546.     }
  547. }
  548.  
  549. void GetRequestTheDM2Way (    VideoRequestRecPtr requestRecPtr,
  550.                             GDHandle walkDevice,
  551.                             DMDisplayModeListIteratorUPP myModeIteratorProc,
  552.                             DMListIndexType theDisplayModeCount,
  553.                             DMListType *theDisplayModeList)
  554. {
  555.     short                    jCount;
  556.     short                    kCount;
  557.     ListIteratorDataRec        searchData;
  558.  
  559.     searchData.depthBlocks = nil;
  560.     // get the mode lists for this GDevice
  561.     for (jCount=0; jCount<theDisplayModeCount; jCount++)        // get info on all the resolution timings
  562.     {
  563.         DMGetIndexedDisplayModeFromList(*theDisplayModeList, jCount, 0, myModeIteratorProc, &searchData);
  564.         
  565.         // for all the depths for this resolution timing (mode)...
  566.         if (searchData.depthBlockCount) for (kCount = 0; kCount < searchData.depthBlockCount; kCount++)
  567.         {
  568.             // print all the timing information 
  569.             printf("Mode: %d, Depth: %d, Resolution: %dH x %dV\n",
  570.                 searchData.depthBlocks[kCount].depthSwitchInfo.csMode,
  571.                 searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize,
  572.                 searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right,
  573.                 searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom);
  574.             printf("Components per Pixel: %d, bits per Component: %d\n",
  575.                 searchData.depthBlocks[kCount].depthVPBlock.vpCmpCount,
  576.                 searchData.depthBlocks[kCount].depthVPBlock.vpCmpSize);
  577.             
  578.             // only if the mode is valid and is safe or we override it with the kAllValidModesBit request flag
  579.             if    (    searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeValid && 
  580.                     (    searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe ||
  581.                         requestRecPtr->requestFlags & 1<<kAllValidModesBit
  582.                     )
  583.                 )
  584.             {
  585.                 if (FindBestMatch (    requestRecPtr,
  586.                                     searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize,
  587.                                     searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right,
  588.                                     searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom))
  589.                 {
  590.                     requestRecPtr->screenDevice = walkDevice;
  591.                     requestRecPtr->availBitDepth = searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize;
  592.                     requestRecPtr->availHorizontal = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right;
  593.                     requestRecPtr->availVertical = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom;
  594.                     
  595.                     // now set the important info for DM to set the display
  596.                     requestRecPtr->depthMode = searchData.depthBlocks[kCount].depthSwitchInfo.csMode;
  597.                     requestRecPtr->displayMode = searchData.depthBlocks[kCount].depthSwitchInfo.csData;
  598.                     requestRecPtr->switchInfo = searchData.depthBlocks[kCount].depthSwitchInfo;
  599.                     if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe)
  600.                         requestRecPtr->availFlags = 0;                            // mode safe
  601.                     else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;    // mode valid but not safe, requires user validation of mode switch
  602.     
  603.                     printf ("requestRecPtr->availBitDepth:%d\n", requestRecPtr->availBitDepth);
  604.                 }
  605.             }
  606.  
  607.         }
  608.     
  609.         // timing flags
  610.         if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeValid)
  611.             printf("mode = %d = valid, ",searchData.displayModeTimingInfo.csTimingFlags);
  612.         else
  613.             printf("mode = %d = invalid, ",searchData.displayModeTimingInfo.csTimingFlags);
  614.         
  615.         if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe)
  616.             printf("safe, ");
  617.         else
  618.             printf("unsafe, ");
  619.     
  620.         if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeDefault)
  621.             printf("default, ");
  622.         else
  623.             printf("not default, ");
  624.     
  625.         if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeShowNow)
  626.             printf("always shown, ");
  627.         else
  628.             printf("not always shown, ");
  629.     
  630.         if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeNotResize)
  631.             printf("no resize, ");
  632.         else
  633.             printf("resizeable, ");
  634.     
  635.         if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeRequiresPan)
  636.             printf("requires pan.\n");
  637.         else
  638.             printf("no pan.\n");
  639.     
  640.         if (searchData.depthBlocks)
  641.         {
  642.             DisposePtr ((Ptr)searchData.depthBlocks);    // toss for this timing mode of this gdevice
  643.             searchData.depthBlocks = nil;                // init it just so we know
  644.         }
  645.     }
  646. }
  647.  
  648. Boolean FindBestMatch (VideoRequestRecPtr requestRecPtr, short bitDepth, unsigned long horizontal, unsigned long vertical)
  649. {
  650.     // •• do the big comparison ••
  651.     // first time only if    (no mode yet) and
  652.     //                        (bounds are greater/equal or kMaximizeRes not set) and
  653.     //                        (depth is less/equal or kShallowDepth not set) and
  654.     //                        (request match or kAbsoluteRequest not set)
  655.     if    (    nil == requestRecPtr->displayMode
  656.             &&
  657.             (    (horizontal >= requestRecPtr->reqHorizontal &&
  658.                 vertical >= requestRecPtr->reqVertical)
  659.                 ||                                                        
  660.                 !(requestRecPtr->requestFlags & 1<<kMaximizeResBit)    
  661.             )
  662.             &&
  663.             (    bitDepth <= requestRecPtr->reqBitDepth ||    
  664.                 !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)        
  665.             )
  666.             &&
  667.             (    (horizontal == requestRecPtr->reqHorizontal &&    
  668.                 vertical == requestRecPtr->reqVertical &&
  669.                 bitDepth == requestRecPtr->reqBitDepth)
  670.                 ||
  671.                 !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  672.             )
  673.         )
  674.         {
  675.             // go ahead and set the new values
  676.             printf ("•1 good to change - first return\n");
  677.             return (true);
  678.         }
  679.     else    // can we do better than last time?
  680.     {
  681.         printf ("have bit priority and avail?\n");
  682.         // if    (kBitDepthPriority set and avail not equal req) and
  683.         //        ((depth is greater avail and depth is less/equal req) or kShallowDepth not set) and
  684.         //        (avail depth less reqested and new greater avail)
  685.         //        (request match or kAbsoluteRequest not set)
  686.         if    (    (    requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit && 
  687.                     requestRecPtr->availBitDepth != requestRecPtr->reqBitDepth
  688.                 )
  689.                 &&
  690.                 (    (    bitDepth > requestRecPtr->availBitDepth &&
  691.                         bitDepth <= requestRecPtr->reqBitDepth
  692.                     )
  693.                     ||
  694.                     !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)    
  695.                 )
  696.                 &&
  697.                 (    requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
  698.                     bitDepth > requestRecPtr->availBitDepth    
  699.                 )
  700.                 &&
  701.                 (    (horizontal == requestRecPtr->reqHorizontal &&    
  702.                     vertical == requestRecPtr->reqVertical &&
  703.                     bitDepth == requestRecPtr->reqBitDepth)
  704.                     ||
  705.                     !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  706.                 )
  707.             )
  708.         {
  709.             // go ahead and set the new values
  710.             printf ("•2 good to change - second return\n");
  711.             return (true);
  712.         }
  713.         else
  714.         {
  715.             printf ("match resolution: minimize Δh & Δv\n");
  716.             // match resolution: minimize Δh & Δv
  717.             if    (    abs((requestRecPtr->reqHorizontal - horizontal)) <=
  718.                     abs((requestRecPtr->reqHorizontal - requestRecPtr->availHorizontal)) &&
  719.                     abs((requestRecPtr->reqVertical - vertical)) <=
  720.                     abs((requestRecPtr->reqVertical - requestRecPtr->availVertical))
  721.                 )
  722.             {
  723.                 printf ("now we have a smaller or same delta\n");
  724.                 // now we have a smaller or equal delta
  725.                 //    if (h or v greater/equal to request or kMaximizeRes not set) 
  726.                 if (    (horizontal >= requestRecPtr->reqHorizontal &&
  727.                         vertical >= requestRecPtr->reqVertical)
  728.                         ||
  729.                         !(requestRecPtr->requestFlags & 1<<kMaximizeResBit)
  730.                     )
  731.                 {
  732.                     printf ("but only if we do not change bit depth\n");
  733.                     // if    (depth is equal or kBitDepthPriority not set) and
  734.                     //        (depth is less/equal or kShallowDepth not set) and
  735.                     //        ([h or v not equal] or [avail depth less reqested and new greater avail] or depth equal avail) and
  736.                     //        (request match or kAbsoluteRequest not set)
  737.                     if    (    (    requestRecPtr->availBitDepth == bitDepth ||            
  738.                                 !(requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit)
  739.                             )
  740.                             &&
  741.                             (    bitDepth <= requestRecPtr->reqBitDepth ||    
  742.                                 !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)        
  743.                             )
  744.                             &&
  745.                             (    (requestRecPtr->availHorizontal != horizontal ||
  746.                                 requestRecPtr->availVertical != vertical)
  747.                                 ||
  748.                                 (requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
  749.                                 bitDepth > requestRecPtr->availBitDepth)
  750.                                 ||
  751.                                 (bitDepth == requestRecPtr->reqBitDepth)
  752.                             )
  753.                             &&
  754.                             (    (horizontal == requestRecPtr->reqHorizontal &&    
  755.                                 vertical == requestRecPtr->reqVertical &&
  756.                                 bitDepth == requestRecPtr->reqBitDepth)
  757.                                 ||
  758.                                 !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  759.                             )
  760.                         )
  761.                     {
  762.                         // go ahead and set the new values
  763.                         printf ("•3 good to change - last return\n");
  764.                         return (true);
  765.                     }
  766.                 }
  767.             }
  768.         }
  769.     }
  770.     return (false);
  771. }
  772.  
  773. void GravitateMonitors (void)
  774. {
  775.     // do the magic gravitation here
  776. }